﻿using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;

namespace Apex.EventBus.Connections
{
    /// <summary>
    /// 表示与 RabbitMQ 的连接
    /// </summary>
    class RabbitMQConnection : IDisposable
    {
        private readonly IConnectionFactory _connectionFactory;
        private IConnection _connection;
        private bool _disposed;
        private readonly object _syncRoot = new object();

        /// <summary>
        /// 初始化 RabbitMQConnection 类的新实例
        /// </summary>
        /// <param name="connectionFactory">用于创建连接的连接工厂</param>
        public RabbitMQConnection(IConnectionFactory connectionFactory)
        {
            _connectionFactory = connectionFactory;
        }

        /// <summary>
        /// 获取一个值，该值指示连接是否打开且未被释放。
        /// </summary>
        public bool IsConnected
        {
            get
            {
                return _connection != null && _connection.IsOpen && !_disposed;
            }
        }

        /// <summary>
        /// 在现有连接上创建一个新的通道/模型来进行消息传递
        /// </summary>
        /// <returns>创建的 IModel 实例。</returns>
        public IModel CreateModel()
        {
            if (!IsConnected)
            {
                throw new InvalidOperationException("无法执行此操作，因为没有可用的 RabbitMQ 连接");
            }

            return _connection.CreateModel();
        }

        /// <summary>
        /// 释放连接
        /// </summary>
        public void Dispose()
        {
            if (_disposed) return;
            _disposed = true;
            _connection.Dispose();
        }

        /// <summary>
        /// 尝试连接到 RabbitMQ
        /// </summary>
        /// <returns>如果连接尝试成功，则为 true；否则为 false</returns>
        public bool TryConnect()
        {
            lock (_syncRoot)
            {
                _connection = _connectionFactory.CreateConnection();

                if (IsConnected)
                {
                    _connection.ConnectionShutdown += OnConnectionShutdown;
                    _connection.CallbackException += OnCallbackException;
                    _connection.ConnectionBlocked += OnConnectionBlocked;
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// 处理连接被阻止的事件
        /// </summary>
        private void OnConnectionBlocked(object sender, ConnectionBlockedEventArgs e)
        {
            if (_disposed) return;
            TryConnect();
        }

        /// <summary>
        /// 处理回调异常事件
        /// </summary>
        private void OnCallbackException(object sender, CallbackExceptionEventArgs e)
        {
            if (_disposed) return;
            TryConnect();
        }

        /// <summary>
        /// 处理连接关闭事件
        /// </summary>
        private void OnConnectionShutdown(object sender, ShutdownEventArgs reason)
        {
            if (_disposed) return;
            TryConnect();
        }
    }
}
